// 滑动窗口（最优解 - 时间复杂度 O(n)）


function LongestSubstring(s) {
  let maxLen = 0;
  const charMap = new Map(); // 存储字符及其最新索引
  let left = 0; // 滑动窗口左边界

  for (let right = 0; right < s.length; right++) {
    const currentChar = s[right];

    // 如果字符已存在且在当前窗口内，移动左边界
    if (charMap.has(currentChar) && charMap.get(currentChar) >= left) {
      left = charMap.get(currentChar) + 1;
    }

    // 更新字符的最新索引
    charMap.set(currentChar, right);

    // 计算当前窗口长度
    maxLen = Math.max(maxLen, right - left + 1);
  }

  return maxLen;
}

// 测试示例
console.log(LongestSubstring("abcabcbb")); // 3 ("abc")
console.log(LongestSubstring("bbbbb"));    // 1 ("b")
console.log(LongestSubstring("pwwkew"));   // 3 ("wke")